package net.blank.world.aStar
{
	import net.blank.functionUtl.ExecFunctions;
	import net.blank.functionUtl.FunctionBinder;
	import net.blank.world.aStar.BHeaps.BPNode;

	/**
	 * 地图节点
	 * @author blank
	 * 
	 */
	public class Node
	{
		/**
		 * 世界坐标_x
		 */
		internal var _world_x:uint;
		
		/**
		 * 世界坐标_y
		 */
		internal var _world_y:uint;
		
		/**
		 * 父节点
		 */
		internal var parent:Node;
		
		/**
		 * 存储二叉堆中的节点(以便快速修正二叉堆节点位置)
		 */
		public var bstNode:BPNode;
		
		/**
		 * 与此节点相邻的可通过的邻节点
		 */
		internal var links:Vector.<Link>=new Vector.<Link>();
		
		/**
		 * 搜索路径的检查编号(确定是否被检查过)
		 */
		internal var searchPathCheckNum:uint;
		
		/**
		 * 可移动范围的检查编号(确定是否被检查过)
		 */
		internal var walkableRangeCheckNum:uint;
		
		/**
		 * 是否能通过
		 */
		internal var _walkable:Boolean;
		
		/**
		 * 此节点代价系数(1表示当前节点的通行代价增加10%,2则表示20%)
		 */
		internal var costMultiplier:int;
		
		/**
		 * 从此节点到目标节点的代价(A星算法使用)
		 */
		public var f:int;
		
		/**
		 * 从起点到此节点的代价
		 */
		internal var g:int;
		
		/**
		 * 在此节点上的单位
		 */
		private var _units:Vector.<IUnit>;
		
		/**
		 * 穿越代价改变的回调函数执行对象
		 */
		private var execFunc_passCost_change:ExecFunctions;
		
		/**
		 * 添加穿越代价被修改后的回调函数
		 * @param callback
		 * @param args
		 * 
		 */
		public function addCallbackFunc_passCost_change(callback:Function,args:Array=null):void{
			execFunc_passCost_change.addFunc(callback,args);
		}
		
		/**
		 * 移除穿越代价被修改后的回调函数
		 * @param callback
		 * 
		 */
		public function rmCallbackFunc_passCost_change(callback:Function):void{
			execFunc_passCost_change.removeFunc(callback);
		}
		
		/**
		 * 刷新穿越代价
		 * 
		 */
		private function refreshPassCost():void{
			var oldValue:int=costMultiplier;
			
			costMultiplier=0;
			for each(var unit:IUnit in _units){
				if(!unit.getIsPassable()){
					if(_walkable){
						_walkable=false;
						execFunc_passCost_change.exec();
					}
					return;
				}
				costMultiplier += unit.getPassCost();
			}
			
			if(costMultiplier != oldValue){
				execFunc_passCost_change.exec();
			}
		}
		
		/**
		 * 单位的可穿越属性发生改变
		 * 
		 */
		private function unit_Passable_changeHandler():void{
			refreshPassCost();
		}
		
		/**
		 * 单位的穿越代价发生改变
		 * 
		 */
		private function unit_passCost_changeHandler():void{
			refreshPassCost();
		}
		
		/**
		 * 添加单位
		 * @param unit 单位
		 * @param index 索引
		 * @return 是否添加成功
		 * 
		 */
		public function addUnit(unit:IUnit):Boolean{
			if(_walkable){
				if(_units.indexOf(unit) == -1){
					FunctionBinder.addBindingFun(unit.setIsPassable,unit_Passable_changeHandler);
					FunctionBinder.addBindingFun(unit.setPassCost,unit_passCost_changeHandler);
					
					_units[_units.length]=unit;
					refreshPassCost();
					
					return true;
				}
			}
			return false;
		}
		
		/**
		 * 移除单位
		 * @param unit 单位
		 * @return 是否移除成功
		 * 
		 */
		public function rmUnit(unit:IUnit):Boolean{
			var index:int=_units.indexOf(unit);
			if(index != -1){
				FunctionBinder.rmBindingFun(unit.setIsPassable,unit_Passable_changeHandler);
				FunctionBinder.rmBindingFun(unit.setPassCost,unit_passCost_changeHandler);
				
				_units.splice(index,1);
				refreshPassCost();
				return true;
			}
			return false;
		}
		
		/**
		 * 获取单位
		 * @param index 索引
		 * @return 
		 * 
		 */
		public function getUnit(index:uint):IUnit{
			if(index < _units.length){
				return _units[index];
			}
			return null;
		}
		
		/**
		 * 获取单位在列表中的索引
		 * @param unit
		 * @return 
		 * 
		 */		
		public function getUnitIndex(unit:IUnit):uint{
			return _units.indexOf(unit);
		}
		
		/**
		 * 地图节点
		 * @param word_x
		 * @param word_y
		 * 
		 */
		public function Node(word_x:uint,word_y:uint){
			_world_x=word_x;
			_world_y=word_y;
			
			_walkable=true;
			_units=new Vector.<IUnit>();
			
			execFunc_passCost_change=new ExecFunctions();
		}
		
		/**
		 * 世界坐标_x
		 * @return 
		 * 
		 */
		public function get world_x():uint{
			return _world_x;
		}
		
		/**
		 * 世界坐标_y
		 * @return 
		 * 
		 */
		public function get world_y():uint{
			return _world_y;
		}
		
		/**
		 * 是否能被穿越
		 * @return 
		 * 
		 */
		public function get walkable():Boolean{
			return _walkable;
		}
		
		/**
		 * 此节点上的单位数
		 * @return 
		 * 
		 */
		public function get unitNum():uint{
			return _units.length;
		}
	}
}